# YunCha-Coffee PyCharm
# user 86155
# 2025/8/30 1:15
from datetime import datetime
from pathlib import Path
import re
from passlib.context import CryptContext  # 需要导入passlib
from fastapi import APIRouter, UploadFile, File, HTTPException, status, Depends
from typing import Union, List, Optional, Any

from tortoise.exceptions import DoesNotExist

from app.dependencies import get_current_user
from app.models import *
from pydantic import BaseModel, validator, ConfigDict

from app.utils.file_handlers import delete_file, save_upload_file


user_api = APIRouter(prefix="/user")
# 密码加密上下文
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
BASE_DIR = Path(__file__).resolve().parent.parent
STATIC_DIR = BASE_DIR / "static"

@user_api.get("/",summary="查询所有用户")
async def getAllUsers():
    # 查询所有
    users = await User.all()


    return {
        "code": 200,
        "message":"查询成功",
        "data":users
    }

@user_api.get("/{id}",summary="查询某一个用户")
async def getOneUser(id:int):

    user = await User.get(id=id)

    return {
        "code":200,
        "message":"查询成功",
        "data":user
    }


# 在你的通用用户更新接口中添加角色处理
class UserRole(str, Enum):
    CUSTOMER = "customer"
    ADMIN = "admin"
    SUPER_ADMIN = "super_admin"


class RoleUpdate(BaseModel):
    role: UserRole


# 在你的后端用户更新接口中
@user_api.put("/{user_id}", response_model=dict)
async def update_user(
        user_id: int,
        user_in: RoleUpdate,
) :
    """
    更新用户信息
    """
    # 检查是否尝试修改自己的角色
    try:
        # 查找用户
        user = await User.get(id=user_id)
    except DoesNotExist:
        raise HTTPException(status_code=404, detail="用户不存在")

    try:
        # 只更新非空字段
        update_data = user_in.dict(exclude_unset=True)

        # 如果没有需要更新的字段，直接返回
        if not update_data:
            return {
                "code": 200,
                "message": "没有需要更新的信息",
                "data": user
            }

        # 更新用户信息
        for field, value in update_data.items():
            if value is not None:
                setattr(user, field, value)
            elif field in ['phone']:  # 允许设置为null的字段
                setattr(user, field, None)

        await user.save()

        return {
            "code": 200,
            "message": "用户信息更新成功",
            "data": user
        }
    except Exception as e:
        raise HTTPException(
            status_code=500,
            detail=f"更新用户信息失败: {str(e)}"
        )


@user_api.post("/",summary="添加用户")
async def addUser():

    return {
        "code":200,
        "message":"添加成功"
    }

@user_api.delete("/{id}",summary="删除用户")
async def deleteUser(id:int):
    await User.filter(id=id).delete()

    return {
        "code":200,
        "message":"删除成功"
    }


class UserOut(BaseModel):
    model_config = ConfigDict(from_attributes=True)

    id: int
    username: str
    email: str
    phone: Optional[str] = None
    created_at: datetime
    updated_at: datetime
    last_login: Optional[datetime] = None
    is_active: bool

    # class Config:
    #     # orm_mode = True
    #     from_attributes = True  # 旧版本叫 orm_mode = True

class UserUpdate(BaseModel):
    username: Optional[str] = None
    email: Optional[str] = None
    phone: Optional[str] = None
    is_active: Optional[bool] = None



@user_api.put("/{id}",summary="修改用户")
async def updateUser(id,user:UserUpdate,):
    """
        修改用户信息

        - **id**: 用户ID
        - **user**: 要修改的用户数据（可选字段）
        """
    try:

        # 将用户要修改的数据做字典化处理，并移除None值
        update_data = user.dict(exclude_unset=True)



        # 更新用户信息
        await User.filter(id=id).update(**update_data)

        # 获取更新后的用户信息
        updated_user = await User.get(id=id)

        return {
            "code": 200,
            "message": "修改成功",
            "data": UserOut.from_orm(updated_user)
        }

    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"修改用户信息失败: {str(e)}"
        )


class UserStatusUpdate(BaseModel):
    is_active: bool


@user_api.put("/{user_id}/status", summary="修改用户状态")
async def update_user_status(user_id: int, status_update: UserStatusUpdate):
    """
    修改用户状态（启用/禁用）

    - **user_id**: 用户ID
    - **status_update**: 状态更新信息
    """
    try:
        # 查找用户
        user = await User.get(id=user_id)
    except DoesNotExist:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="用户不存在"
        )

    try:
        # 更新用户状态
        user.is_active = status_update.is_active
        user.updated_at = datetime.now()
        await user.save()

        status_text = "启用" if status_update.is_active else "禁用"

        return {
            "code": 200,
            "message": f"用户已{status_text}",
            "data": UserOut.from_orm(user)
        }
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"更新用户状态失败: {str(e)}"
        )


@user_api.put("/{id}/avatar", summary="上传用户头像", status_code=status.HTTP_200_OK)
async def upload_user_avatar(
        id: int,
        avatar: UploadFile = File(...)  # 添加权限验证
):
    """
    上传用户头像

    - **id**: 用户ID
    - **avatar**: 头像图片文件 (支持 jpeg, png, gif, webp 格式，最大 5MB)
    """
    try:
        # 检查用户是否存在
        user = await User.get(id=id)

        # 删除旧头像（如果存在）
        if user.head_image:
            await delete_file(user.head_image)

        # 保存新头像 - 使用新的函数签名
        avatar_info = await save_upload_file(avatar, "user_avatars")
        avatar_path = avatar_info["file_path"]

        # 更新用户记录
        user.head_image = avatar_path
        await user.save()

        return {
            "code": 200,
            "message": "头像上传成功",
            "data": {
                "avatar_url": avatar_info["file_url"]  # 使用返回的完整URL
            }
        }
    except DoesNotExist:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="用户不存在"
        )
    except HTTPException as e:
        # 重新抛出HTTP异常（如文件类型或大小错误）
        raise e
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"上传失败: {str(e)}"
        )


@user_api.delete("/{id}/avatar", summary="删除用户头像", status_code=status.HTTP_200_OK)
async def delete_user_avatar(
        id: int
):
    """
    删除用户头像

    - **id**: 用户ID
    """
    try:
        # 检查用户是否存在
        user = await User.get(id=id)

        if user.head_image:
            # 删除文件 - 使用新的函数签名
            await delete_file(user.head_image)

            # 更新用户记录
            user.head_image = None
            await user.save()

        return {
            "code": 200,
            "message": "头像删除成功"
        }
    except DoesNotExist:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="用户不存在"
        )
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"删除失败: {str(e)}"
        )


# 密码修改相关模型
class PasswordChange(BaseModel):
    current_password: str
    new_password: str
    confirm_password: str

    @validator('new_password')
    def validate_password(cls, v):
        """验证密码强度"""
        if len(v) < 8:
            raise ValueError('密码长度至少为8个字符')
        if not re.search(r'[A-Z]', v):
            raise ValueError('密码必须包含至少一个大写字母')
        if not re.search(r'[a-z]', v):
            raise ValueError('密码必须包含至少一个小写字母')
        if not re.search(r'[0-9]', v):
            raise ValueError('密码必须包含至少一个数字')
        if not re.search(r'[!@#$%^&*(),.?":{}|<>]', v):
            raise ValueError('密码必须包含至少一个特殊字符')
        return v

    @validator('confirm_password')
    def passwords_match(cls, v, values, **kwargs):
        """验证两次输入的密码是否一致"""
        if 'new_password' in values and v != values['new_password']:
            raise ValueError('两次输入的新密码不一致')
        return v


@user_api.put("/{id}/password_hash", summary="修改用户密码", status_code=status.HTTP_200_OK)
async def change_user_password(id: int, password_data: PasswordChange):
    """
    修改用户密码

    -** id **: 用户ID
    -** current_password **: 当前密码（用于验证）
    -** new_password **: 新密码（需符合强度要求）
    -** confirm_password **: 确认新密码
    """
    try:
        # 检查用户是否存在
        user = await User.get(id=id)

        # 验证当前密码是否正确
        if not pwd_context.verify(password_data.current_password, user.password_hash):
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="当前密码不正确"
            )

        # 检查新密码是否与当前密码相同
        if pwd_context.verify(password_data.new_password, user.password_hash):
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="新密码不能与当前密码相同"
            )

        # 加密新密码并更新
        hashed_password = pwd_context.hash(password_data.new_password)
        user.password_hash = hashed_password
        user.updated_at = datetime.now()  # 更新修改时间
        await user.save()

        return {
            "code": 200,
            "message": "密码修改成功，请使用新密码登录"
        }

    except DoesNotExist:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="用户不存在"
        )
    except HTTPException as e:
        raise e
    except Exception as e:
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail=f"密码修改失败: {str(e)}"
        )


